package com.frank.loadinglibrary.special.element;

import com.frank.loadinglibrary.base.baseanimations.BaseAnimationController;
import com.frank.loadinglibrary.base.baseelement.BaseElement;
import com.frank.loadinglibrary.base.baseelement.IComponentCallback;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import java.util.ArrayList;

/**
 * @author SUQI
 * @date 2021/6/3
 * @description
 **/
public class EatBeansElement extends BaseElement implements BaseAnimationController.IAnimationController<AnimatorValue> {

    public final static int LINE = 1;
    public final static int CIRCLE = 2;

    private int viewType;
    private Paint mPaint;
    private Paint mPaintEye;
    private float mPadding = 5f;
    private float eatErWidth;
    private float eatErPositionX = 0f;
    private float eatErPositionY = 0f;
    private int eatSpeed = 5;
    private float beansWidth;
    private int beansCount;
    private float mAngle = 30;
    private float eatErStartAngle = mAngle;
    private float eatErEndAngle = 360 - 2 * eatErStartAngle;
    private int animatorTime;
    private float radius;
    private float moveAngle;
    private Color beansColor;
    private Color eatErColor;

    private EatBeansElement(IComponentCallback iComponentCallback) {
        this.callback = iComponentCallback;
    }

    @Override
    public ArrayList<AnimatorValue> onCreateAnimators() {
        ArrayList<AnimatorValue> list = new ArrayList<>();
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setLoopedCount(Animator.INFINITE);
        animatorValue.setDuration(animatorTime);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            if (viewType == LINE) {
                eatErPositionX = (getWidth() - 2 * mPadding - eatErWidth) * v;
                eatErStartAngle = mAngle * (1 - (v * eatSpeed - (int) (v * eatSpeed)));
                eatErEndAngle = 360 - eatErStartAngle * 2;
            } else {
                moveAngle = 360 * v;
                eatErPositionY = (float) (getHeight() / 2 - Math.sin(Math.toRadians(360 * v)) * radius);
                eatErPositionX = (float) (getWidth() / 2 - Math.cos(Math.toRadians(360 * v)) * radius);
                float rate = (float) Math.abs(Math.sin(Math.toRadians(moveAngle * 4)));
                eatErStartAngle = 300 + moveAngle - mAngle * rate;
                eatErEndAngle = 300 + 2 * mAngle * rate;
            }
            callback.reflushComponent();
        });
        list.add(animatorValue);
        return list;
    }

    @Override
    public void onAnimationReset() {
        //do nothing because donot need to reset animation params
    }

    @Override
    public BaseAnimationController.IAnimationController<AnimatorValue> initAnimationController() {
        return this;
    }

    @Override
    public void initPaint() {
        super.initPaint();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mPaint.setColor(eatErColor);

        mPaintEye = new Paint();
        mPaintEye.setAntiAlias(true);
        mPaintEye.setStyle(Paint.Style.FILL_STYLE);
        mPaintEye.setColor(beansColor);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        radius = Math.min(getWidth(), getHeight()) / 2 - 60;
        mPaint.setColor(eatErColor);
        mPaintEye.setColor(beansColor);

        if (viewType == LINE) {
            float eatRightX = mPadding + eatErWidth + eatErPositionX;
            RectFloat rectF = new RectFloat(mPadding + eatErPositionX, getHeight() / 2 - eatErWidth / 2, eatRightX, getHeight() / 2 + eatErWidth / 2);
            canvas.drawArc(rectF, new Arc(eatErStartAngle, eatErEndAngle, true), mPaint);
            canvas.drawCircle(mPadding + eatErPositionX + eatErWidth / 2, getHeight() / 2 - eatErWidth / 4, beansWidth / 2, mPaintEye);
            for (int i = 0; i < beansCount; i++) {
                float x = beansCount * i + beansWidth / 2 + mPadding + eatErWidth;
                if (x > eatRightX) {
                    canvas.drawCircle(x, getHeight() / 2, beansWidth / 2, mPaint);
                }
            }
        } else {
            RectFloat rectF = new RectFloat(eatErPositionX - eatErWidth / 2, eatErPositionY - eatErWidth / 2, eatErPositionX + eatErWidth / 2, eatErPositionY + eatErWidth / 2);
            canvas.drawArc(rectF, new Arc(eatErStartAngle, eatErEndAngle, true), mPaint);
            canvas.drawCircle((float) (getWidth() / 2 - Math.cos(Math.toRadians(moveAngle + 5)) * (radius + eatErWidth / 4)),
                    (float) (getHeight() / 2 - Math.sin(Math.toRadians(moveAngle + 5)) * (radius + eatErWidth / 4)), beansWidth / 2, mPaintEye);
            int angleAverage = 360 / beansCount;
            for (int i = 0; i < beansCount; i++) {
                if (i * angleAverage >= moveAngle) {
                    canvas.rotate(-angleAverage, getWidth() / 2, getHeight() / 2);
                    canvas.drawCircle((float) (getWidth() / 2 - Math.cos(Math.toRadians(0)) * radius), getHeight() / 2, beansWidth / 2, mPaintEye);
                }
            }
        }
    }

    private void apply(EatBeanBuilder builder) {
        this.beansWidth = builder.beansWidth;
        this.viewType = builder.viewType;
        this.eatErWidth = builder.eatErWidth;
        this.beansColor = builder.beansColor;
        this.eatErColor = builder.eatErColor;
        this.animatorTime = builder.animatorTime;
        this.beansCount = builder.beansCount;
    }

    public static class EatBeanBuilder {
        private IComponentCallback iComponentCallback;
        private float beansWidth = 10f;
        private int viewType = CIRCLE;
        private float eatErWidth = 40f;
        private Color beansColor = Color.WHITE;
        private Color eatErColor = Color.BLACK;
        private int animatorTime = 10000;
        private int beansCount = 10;

        public EatBeanBuilder setBeansWidth(float beansWidth) {
            this.beansWidth = beansWidth;
            return this;
        }

        public EatBeanBuilder setViewType(int viewType) {
            this.viewType = viewType;
            return this;
        }

        public EatBeanBuilder setEatErWidth(float eatErWidth) {
            this.eatErWidth = eatErWidth;
            return this;
        }

        public EatBeanBuilder setBeansColor(Color beansColor) {
            this.beansColor = beansColor;
            return this;
        }

        public EatBeanBuilder setEatErColor(Color eatErColor) {
            this.eatErColor = eatErColor;
            return this;
        }

        public EatBeanBuilder setAnimatorTime(int animatorTime) {
            this.animatorTime = animatorTime;
            return this;
        }

        public EatBeanBuilder setBeansCount(int beansCount) {
            this.beansCount = beansCount;
            return this;
        }


        public EatBeanBuilder(IComponentCallback iComponentCallback) {
            this.iComponentCallback = iComponentCallback;
        }

        public EatBeansElement build() {
            EatBeansElement eatBeansElement = new EatBeansElement(this.iComponentCallback);
            eatBeansElement.apply(this);
            return eatBeansElement;
        }
    }
}
